﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using ZYLFramework.Common;

namespace ZYLFramework.Manage
{
    /// <summary>
    /// 按钮监听委托
    /// </summary>
    public delegate void KeyDelegate();
    
    /// <summary>
    /// 按键事件
    /// </summary> 
    public class InputEvent
    {
        /// <summary>
        /// 监听的按键
        /// </summary>
        public KeyCode KeyCode;
        /// <summary>
        /// 长按按下事件
        /// </summary>
        public KeyDelegate PressEventFunc;
        /// <summary>
        /// 长按放弃事件
        /// </summary>
        public KeyDelegate WaivePressEventFunc;
        /// <summary>
        /// 按键完成事件
        /// </summary>
        public KeyDelegate CompletePressEventFunc;
        /// <summary>
        /// 按钮触发长按时间，为0为非长按
        /// </summary>
        public int LongPress;
        /// <summary>
        /// true监听按下 false 监听抬起
        /// </summary>
        public bool IsDown;
        /// <summary>
        /// 当前事件索引
        /// </summary>
        public int EventId;

        /// <summary>
        /// 短按按键事件构造
        /// </summary> 
        public InputEvent(KeyCode keyCode,
            KeyDelegate eventFunc,
            bool isDown)
        {
            KeyCode = keyCode;
            CompletePressEventFunc = eventFunc;
            LongPress = 0;
            IsDown = isDown;
        }

        /// <summary>
        /// 长按按键事件构造
        /// </summary>
        public InputEvent(KeyCode keyCode,int longPress,
            KeyDelegate pressEventFunc,
            KeyDelegate waivePressEventFunc,
            KeyDelegate completePressEventFunc)
        {
            KeyCode = keyCode;
            LongPress = longPress;
            PressEventFunc = pressEventFunc;
            WaivePressEventFunc = waivePressEventFunc;
            CompletePressEventFunc = completePressEventFunc;
        }
    }
    public class InputManager:MonoSingleton<InputManager>
    {
        
        
        private bool _openListen;

        //事件总表
        private List<InputEvent> _eventList;
        //事件Key分类表
        private Dictionary<KeyCode, List<int>> _eventMgr;
        //删除表
        private List<int> _removeEventMgr;
        //完成事件定时器对应表
        private Dictionary<int,int> _completeEventsTimer;
        //开始长按事件定时器对应表
        private Dictionary<int,int> _pressEventsTimer;

        protected override void Awake()
        {
            base.Awake();
            _eventList = new List<InputEvent>();
            _eventMgr = new Dictionary<KeyCode, List<int>>();
            _removeEventMgr = new List<int>();
            _completeEventsTimer = new Dictionary<int, int>();
            _pressEventsTimer = new Dictionary<int, int>();
        }

        /// <summary>
        /// 监听按键输入
        /// </summary>
        /// <param name="keyCode">监听的按键</param>
        /// <param name="eventFunc">回调委托</param>
        /// <param name="isDown">是否监听按下，false为监听抬起 长按时强制为按下</param>
        public void AddKeyListen(KeyCode keyCode,KeyDelegate eventFunc,bool isDown = true)
        {
            AddEvent(new InputEvent(keyCode,eventFunc,isDown));
        }

        /// <summary>
        /// 监听长按按键输入
        /// </summary>
        /// <param name="keyCode">监听的按键</param>
        /// <param name="longPress">长按延时，默认为0效果为短按 单位为10毫秒 1s为100</param>
        /// <param name="pressEventFunc">按下回调委托</param>
        /// <param name="waivePressEventFunc">放弃回调委托</param>
        /// <param name="completePressEventFunc">成功回调委托</param>
        public void AddLongPressKeyListen(KeyCode keyCode,int longPress,
            KeyDelegate pressEventFunc,
            KeyDelegate waivePressEventFunc,
            KeyDelegate completePressEventFunc)
        {
            AddEvent(new InputEvent(keyCode,longPress,pressEventFunc,waivePressEventFunc,completePressEventFunc));
        }

        public void AddEvent(InputEvent inputEvent)
        {
            _eventList.Add(inputEvent); 
            var index = _eventList.Count-1;
            _eventList[index].EventId = index;
            if (!_eventMgr.ContainsKey(inputEvent.KeyCode))
            {
                _eventMgr.Add(inputEvent.KeyCode,new List<int>()); 
            }
            _eventMgr[inputEvent.KeyCode].Add(index);
        }
        
        public void RemoveEvent(int index)
        {
            var temp = _eventList[index];
            if (temp == null)
            {
               return; 
            }
            var keyCode = temp.KeyCode;
            _eventMgr[keyCode].Remove(index);
            _eventList.RemoveAt(index);
        }

        private void Update()
        {
            var keyCodeList = _eventMgr.Keys.ToArray();
            foreach (var v in keyCodeList)
            {
                for (int i = 0; i < _eventMgr[v].Count; i++)
                {
                    var inputEventInfo = _eventList[_eventMgr[v][i]];
                    var eventId = inputEventInfo.EventId;

                    // 如果是长按
                    if (inputEventInfo.LongPress > 0)
                    {
                        if (!_completeEventsTimer.ContainsKey(eventId))
                        {
                            //如果初次按下且没有定时器
                           if (Input.GetKeyDown(v))
                           {
                                var timerHandler = TimerManage.Instance.Schedule(delegate
                                {
                                    inputEventInfo.CompletePressEventFunc?.Invoke();
                                }, inputEventInfo.LongPress / 100f,1,1); 
                                _completeEventsTimer.Add(eventId,timerHandler); 
                           } 
                        }
                        else
                        {
                            //默认开始按下的触发为0.2秒
                            if (Input.GetKey(v))
                            {
                                inputEventInfo.PressEventFunc?.Invoke();
                            }
                            
                            //如果有定时器，松开了按键
                            if (Input.GetKeyUp(v))
                            {
                                var timerHandler = _completeEventsTimer[eventId];
                                TimerManage.Instance.Unschedule(timerHandler);
                                _completeEventsTimer.Remove(eventId);
                                if (_pressEventsTimer.ContainsKey(eventId))
                                {
                                    timerHandler = _pressEventsTimer[eventId];
                                    TimerManage.Instance.Unschedule(timerHandler);
                                    _pressEventsTimer.Remove(eventId); 
                                }
                                inputEventInfo.WaivePressEventFunc?.Invoke();
                            }
                        }
                    }
                    else
                    {
                        //区分监听的是抬起还是放下
                        if (inputEventInfo.IsDown?Input.GetKeyDown(v):Input.GetKeyUp(v))
                        {
                            inputEventInfo.CompletePressEventFunc?.Invoke(); 
                        }
                    }
                    
                }

            }

            foreach (var evenId in _removeEventMgr)
            {
                RemoveEvent(evenId);
            }
        }
    }
}